package com.focus.xyz.core.common.webdriver;

import com.focus.xyz.core.utils.EncryptUtil;
import com.focus.xyz.core.utils.prop.ConfigPropInfo;
import com.gargoylesoftware.htmlunit.DefaultCredentialsProvider;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.LogFactory;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeDriverService;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.firefox.internal.ProfilesIni;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.ie.InternetExplorerDriverService;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriverService;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ThreadGuard;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


public class LocalDriver implements IDriver {
    private static boolean isNeedProxy = false;
    private WebDriver driver;
    private DesiredCapabilities capabilities;
    private SeleConst.DeviceEnum device;


    public LocalDriver getDevice(String device) {
        this.device = SeleConst.DeviceEnum.getDevice(device);
        return this;
    }

    public WebDriver getBrowser(String browser) throws Exception {
        switch (SeleConst.DriverEnum.getEnum(browser)) {
            case CHROME: {
                System.out.println(browser);
                System.setProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY, ConfigPropInfo.DRIVER_DIR + SeleConst.DriverEnum.CHROME.getCode());
                ChromeDriverService.Builder builder = new ChromeDriverService.Builder();
                builder = builder.usingDriverExecutable(new File(ConfigPropInfo.DRIVER_DIR + SeleConst.DriverEnum.CHROME.getDriver()));
                if (ConfigPropInfo.CHROME_PORT_ISFIXED) {
                    builder.usingPort(Integer.valueOf(ConfigPropInfo.CHROME_PORT));
                } else {
                    builder.usingAnyFreePort();
                }
                ChromeDriverService chromeService = builder.build();
                try {
                    chromeService.start();
                    driver = new ChromeDriver(chromeService, chromeOptions());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            }
            case IE: {
                System.out.println(browser);
                System.setProperty(InternetExplorerDriverService.IE_DRIVER_EXE_PROPERTY, ConfigPropInfo.DRIVER_DIR + SeleConst.DriverEnum.IE.getDriver());
                capabilities = DesiredCapabilities.internetExplorer();
                capabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
                driver = new InternetExplorerDriver(capabilities);
                break;
            }
            case FIREFOX: {
                System.out.println(browser);
                ProfilesIni allProfiles = new ProfilesIni();
                FirefoxProfile profile = allProfiles.getProfile("selenium");
                driver = new FirefoxDriver(profile);
                break;
            }
            case HTMLUNIT: {
                LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.NoOpLog");//关闭htmlunit运行时日志
                capabilities = DesiredCapabilities.htmlUnitWithJs();
                if (StringUtils.isNotBlank(ConfigPropInfo.IS_NEED_PROXY)) {
                    isNeedProxy = Boolean.valueOf(ConfigPropInfo.IS_NEED_PROXY);
                }
                if (isNeedProxy) {
                    if (StringUtils.isBlank(ConfigPropInfo.PROXY_HOST)) {
                        throw new Exception("代理主机地址为空");
                    }
                    if (StringUtils.isBlank(ConfigPropInfo.PROXY_PORT)) {
                        throw new Exception("代理主机端口为空");
                    }
                    Proxy proxy = new Proxy();
                    proxy.setHttpProxy(ConfigPropInfo.PROXY_HOST + ":" + ConfigPropInfo.PROXY_PORT);
                    capabilities.setCapability(CapabilityType.PROXY, proxy);
                    capabilities.setBrowserName("chrome");
                    driver = new HtmlUnitDriver(capabilities) {
                        @Override
                        protected WebClient modifyWebClient(WebClient client) {
                            if (StringUtils.isNotBlank(ConfigPropInfo.USERNAME) && StringUtils.isNotBlank(ConfigPropInfo.PASSWORD)) {
                                try {
                                    DefaultCredentialsProvider creds = new DefaultCredentialsProvider();
                                    String depass = EncryptUtil.decrypt(ConfigPropInfo.PASSWORD);
                                    creds.addCredentials(ConfigPropInfo.USERNAME, depass);
                                    client.setCredentialsProvider(creds);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                            client.getBrowserVersion().setBrowserVersion(49.0f);
                            client.getOptions().setCssEnabled(true);
                            client.getOptions().setJavaScriptEnabled(true);
                            client.getOptions().setUseInsecureSSL(true);
                            client.setAjaxController(new NicelyResynchronizingAjaxController());
                            client.getOptions().setTimeout(10000);
                            client.getOptions().setThrowExceptionOnScriptError(false);
                            client.waitForBackgroundJavaScript(10000);
                            client.waitForBackgroundJavaScriptStartingBefore(10000l);
                            return client;
                        }
                    };
                } else {
                    driver = new HtmlUnitDriver(capabilities);
                }
                break;
            }
            case PHANTOMJS: {
                PhantomJSDriverService.Builder builder = new PhantomJSDriverService.Builder();
                PhantomJSDriverService plantomService = builder.usingPhantomJSExecutable(new File(ConfigPropInfo.DRIVER_DIR + SeleConst.DriverEnum.PHANTOMJS.getDriver())).usingAnyFreePort().build();
                plantomService.start();
                capabilities = DesiredCapabilities.phantomjs();
                driver = new PhantomJSDriver(plantomService, capabilities);
                break;
            }
            case DEFULAT: {
                System.out.println("default");
                System.setProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY, ConfigPropInfo.DRIVER_DIR + SeleConst.DriverEnum.DEFULAT.getDriver());
                if (StringUtils.isNotBlank(ConfigPropInfo.CHROME_BIN)) {
                    System.setProperty("webdriver.chrome.bin", ConfigPropInfo.CHROME_BIN);
                }
                capabilities = DesiredCapabilities.chrome();
                if(device != null && StringUtils.isNotBlank(device.getCode())){
                    Map<String, String> mobileEmulation = new HashMap<String, String>();
                    mobileEmulation.put("deviceName", device.getCode());
                    Map<String, Object> chromeOptions = new HashMap<String, Object>();
                    chromeOptions.put("mobileEmulation", mobileEmulation);
                    capabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
                }
                driver = new ChromeDriver(capabilities);
                driver.manage().window().setSize(device.getSize());
                break;
            }
        }
        driver.manage().timeouts().implicitlyWait(ConfigPropInfo.DRIVER_IMPLICITLY_WAIT, TimeUnit.MILLISECONDS);
        if(true){
            driver = ThreadGuard.protect(driver);
        }
        return driver;
    }

    private DesiredCapabilities chromeOptions() {
        ChromeOptions options = new ChromeOptions();
        capabilities = DesiredCapabilities.chrome();
        capabilities.setCapability("chrome.switches", Arrays.asList("--start-maximized"));
        options.addArguments("--test-type", "--start-maximized");
        options.addArguments("--test-type", "--ignore-certificate-errors");
        if (StringUtils.isNotBlank(ConfigPropInfo.CHROME_BIN)) {
            options.setBinary(ConfigPropInfo.CHROME_BIN);
        }
        capabilities.setCapability(ChromeOptions.CAPABILITY, options);
        return capabilities;
    }

    public static void main(String[] args) throws Exception {
        LocalDriver localDriver = new LocalDriver();
        localDriver.getDevice("iphone6").getBrowser("chrome1");
    }
}
